package org.example.learn.bytebuddy.monitor;

import net.bytebuddy.implementation.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.Callable;

// 监控方法耗时
public class Monitor {

    // @RuntimeType 定义运行时的目标方法
    // @SuperCall 用于调用父类版本的方法
    @RuntimeType
    public static Object intercept(@SuperCall Callable<?> callable) {
        long startTime = System.currentTimeMillis();
        Object val = null;
        try {
            val = callable.call();// 调用原方法的内容，并返回结果
            return val;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            System.out.println("方法耗时：" + (System.currentTimeMillis() - startTime) + "ms");
            System.out.println("结果内容： " + val);
        }
        return null;
    }

    // @Origin 用于拦截原有方法，可以获取到原有方法中的相关信息
    @RuntimeType
    public static Object intercept(@Origin Method method,@SuperCall Callable<?> callable) {
        long startTime = System.currentTimeMillis();
        Object val = null;
        try {
            val = callable.call();
            return val;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            System.out.println("方法名称： " + method.getName());
            System.out.println("入参个数： " + method.getParameterCount());
            System.out.println("入参类型： " + Arrays.toString(method.getParameterTypes()));
            System.out.println("出参类型： " + method.getReturnType());
            System.out.println("出参结果： " + val);
            System.out.println("方法耗时： " + (System.currentTimeMillis() - startTime) + "ms");
        }
        return null;
    }

    // @AllArguments 绑定全部参数的数组
    // @Argument 绑定单个参数
    @RuntimeType
    public static Object intercept(@Origin Method method, @AllArguments Object[] args, @Argument(0) Object arg0,@SuperCall Callable<?> callable){
        long startTime = System.currentTimeMillis();
        Object val = null;
        try {
            val = callable.call();
            return val;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("方法名称： " + method.getName());
            System.out.println("入参个数： " + method.getParameterCount());
            System.out.println("入参类型： " + Arrays.toString(method.getParameterTypes()));
            System.out.println("入参内容： " + Arrays.toString(args));
            System.out.println("第一个入参内容: " + arg0);
            System.out.println("出参类型： " + method.getReturnType());
            System.out.println("出参结果： " + val);
            System.out.println("方法耗时： " + (System.currentTimeMillis() - startTime) + "ms");
        }
        return null;
    }
}
